﻿
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#include "CustomizerGStyleManager.h"
#include "IElement.h"
#include "FilePath.h"
#include "ICategory.h"
#include "UniIdentity.h"
#include "IUiDocument.h"
#include "ElementUtils.h"
#include "DbObjectUtils.h"
#include "IGraphicsStyle.h"
#include "IElementStatus.h"
#include "GbmpFileSystem.h"
#include "IGenericElement.h"
#include "IUserTransaction.h"
#include "ICategoryLibrary.h"
#include "IGraphicsStyleData.h"
#include "IGraphicsStyleManager.h"
#include "ElementCreationOptions.h"
#include "IUiDocumentViewManager.h"
#include "GcmpBuiltInCategoryUniIdentities.h"

#include "GraphicsStyleConfig.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace Sample;
using namespace gcmp;

static const std::unordered_map<std::wstring, gcmp::ElementId, std::hash<std::wstring>> s_emptyStringElementIdMap = std::unordered_map<std::wstring, gcmp::ElementId, std::hash<std::wstring>>();
static const std::unordered_map<gcmp::UniIdentity, gcmp::ElementId, gcmp::UniIdentityHash> s_emptyUniIdentityElementIdMap = std::unordered_map<gcmp::UniIdentity, gcmp::ElementId, gcmp::UniIdentityHash>();

// 用于图元的图形节点按照样式类别做显示样式重载的四个类别
const UniIdentity CustomizerGStyleManager::s_category_id_CategoryA = UniIdentity::Create(GuidUtils::FromString(L"{4A169235-F015-480A-B430-67B8AFAA78D7}"), L"类别A");
const UniIdentity CustomizerGStyleManager::s_category_id_CategoryB = UniIdentity::Create(GuidUtils::FromString(L"{50A5C756-8267-4FF5-8879-4D4E54596E06}"), L"类别B");
const UniIdentity CustomizerGStyleManager::s_category_id_CategoryC = UniIdentity::Create(GuidUtils::FromString(L"{A27C0B92-21E8-43B4-A525-941359E7A768}"), L"类别C");
const UniIdentity CustomizerGStyleManager::s_category_id_CategoryD = UniIdentity::Create(GuidUtils::FromString(L"{D0CF4F51-C115-44E4-A06A-CFF5BFFD6786}"), L"类别D");

DATA_DEFINE(ElementGStyleData)
{
    m_ElementGStyle = ElementId::InvalidID;
}

gcmp::OwnerPtr<ElementGStyleData> ElementGStyleData::Create()
{
    gcmp::OwnerPtr<ElementGStyleData> opResult = NEW_AS_OWNER_PTR(ElementGStyleData);
    return TransferOwnership(opResult);
}

NdbObject * Sample::ElementGStyleData::GetTopOwnerObject() const
{
    IUiDocument* pUiDoc = IUiDocumentViewManager::Get()->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMP",L"2024-03-30");
    IDocument* pDoc = pUiDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMP",L"2024-03-30");
    // 会返回当前文档的单例CustomizerGStyleManager，从而在ElementGStyleData改变时，NDB会在事务中自动处理
    CustomizerGStyleManager* pCustomizerGStyleManager = CustomizerGStyleManager::Get(pDoc);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCustomizerGStyleManager, L"pCustomizerGStyleManager为空", L"GDMP", L"2024-03-30");
    return gcmp::quick_cast<NdbObject>(pCustomizerGStyleManager);
}

bool Sample::ElementGStyleData::GetElementGStyle(gcmp::ElementId & gStyleId) const
{
    gStyleId = GetElementGStyle__();
    return gStyleId.IsValid();
}

bool Sample::ElementGStyleData::GetViewElementGStyle(gcmp::ElementId viewId, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* pData;
    bool exist = GetViewMap(viewId, pData);
    if (!exist) return false;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pData, L"pData为空",L"GDMP",L"2024-03-30");
    return pData->GetElementGStyle(gStyleId);
}

bool Sample::ElementGStyleData::GetGNodeNameGStyle(std::wstring gNodeName, gcmp::ElementId & gStyleId) const
{
    const auto& constMap = GetGNodeNameToGNodeGStyleMap__();
    const auto& iter = constMap.find(gNodeName);
    if (iter == constMap.end())
    {
        return false;
    }
    else
    {
        gStyleId = iter->second;
        return true;
    }
}

bool Sample::ElementGStyleData::GetGNodeCategoryGStyle(gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId) const
{
    const auto& constMap = GetGNodeCategoryToGNodeGStyleMap__();
    const auto& iter = constMap.find(gNodeCategory);
    if (iter == constMap.end())
    {
        return false;
    }
    else
    {
        gStyleId = iter->second;
        return true;
    }
}

bool Sample::ElementGStyleData::GetViewGNodeNameGStyle(gcmp::ElementId viewId, std::wstring gNodeName, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* pData;
    bool exist = GetViewMap(viewId, pData);
    if (!exist) return false;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pData, L"pData为空",L"GDMP",L"2024-03-30");
    return pData->GetGNodeNameGStyle(gNodeName, gStyleId);
}

bool Sample::ElementGStyleData::GetViewGNodeCategoryGStyle(gcmp::ElementId viewId, gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* pData;
    bool exist = GetViewMap(viewId, pData);
    if (!exist) return false;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pData, L"pData为空",L"GDMP",L"2024-03-30");
    return pData->GetGNodeCategoryGStyle(gNodeCategory, gStyleId);
}

void Sample::ElementGStyleData::UpdateElementGStyle(gcmp::ElementId & gStyleId)
{
    GetElementGStyleFW__();
    SetElementGStyle__(gStyleId);
}

void Sample::ElementGStyleData::UpdateViewElementGStyle(gcmp::ElementId viewId, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* pViewData = GetOrAddViewMap(viewId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pViewData, L"pViewData为空",L"GDMP",L"2024-03-30");
    pViewData->UpdateElementGStyle(gStyleId);
}

void Sample::ElementGStyleData::UpdateGNodeNameGStyle(std::wstring gNodeName, gcmp::ElementId & gStyleId)
{
    auto& mutableMap = GetGNodeNameToGNodeGStyleMapFW__();
    mutableMap[gNodeName] = gStyleId;
}

void Sample::ElementGStyleData::UpdateGNodeCategoryGStyle(gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId)
{
    auto& mutableMap = GetGNodeCategoryToGNodeGStyleMapFW__();
    mutableMap[gNodeCategory] = gStyleId;
}

void Sample::ElementGStyleData::UpdateViewGNodeNameGStyle(gcmp::ElementId viewId, std::wstring gNodeName, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* pViewData = GetOrAddViewMap(viewId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pViewData, L"pViewData为空",L"GDMP",L"2024-03-30");
    pViewData->UpdateGNodeNameGStyle(gNodeName, gStyleId);
}

void Sample::ElementGStyleData::UpdateViewGNodeCategoryGStyle(gcmp::ElementId viewId, gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* pViewData = GetOrAddViewMap(viewId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pViewData, L"pViewData为空",L"GDMP",L"2024-03-30");
    pViewData->UpdateGNodeCategoryGStyle(gNodeCategory, gStyleId);
}

bool Sample::ElementGStyleData::GetViewMap(gcmp::ElementId viewId, const ElementGStyleData*& pViewData) const
{
    const auto& constMap = GetViewLevelGNodeGStyleMap__();
    const auto& iter = constMap.find(viewId);
    if (iter != constMap.end())
    {
        pViewData = iter->second.get();
        return true;
    }
    return false;
}

ElementGStyleData* Sample::ElementGStyleData::GetOrAddViewMap(gcmp::ElementId viewId)
{
    auto& mutableMap = GetViewLevelGNodeGStyleMapFW__();
    const auto& iter = mutableMap.find(viewId);
    if (iter == mutableMap.end())
    {
        mutableMap[viewId] = TransferOwnership(NEW_AS_OWNER_PTR(ElementGStyleData));
    }
    return mutableMap.find(viewId)->second.get();
}

const std::unordered_map<std::wstring, gcmp::ElementId, std::hash<std::wstring>>& Sample::ElementGStyleData::GetGNodeNameGStyles() const
{
    return GetGNodeNameToGNodeGStyleMap__();
}

const std::unordered_map<gcmp::UniIdentity, gcmp::ElementId, gcmp::UniIdentityHash>& Sample::ElementGStyleData::GetGNodeCategoryGStyles() const
{
    return GetGNodeCategoryToGNodeGStyleMap__();
}

const std::unordered_map<std::wstring, gcmp::ElementId, std::hash<std::wstring>>& Sample::ElementGStyleData::GetViewGNodeNameGStyles(gcmp::ElementId viewId) const
{
    const auto& constMap = GetViewLevelGNodeGStyleMap__();
    const auto& iter = constMap.find(viewId);
    if (iter != constMap.end())
    {
        return iter->second->GetGNodeNameToGNodeGStyleMap__();
    }
    return s_emptyStringElementIdMap;
}

const std::unordered_map<gcmp::UniIdentity, gcmp::ElementId, gcmp::UniIdentityHash>& Sample::ElementGStyleData::GetViewGNodeCategoryGStyles(gcmp::ElementId viewId) const
{
    const auto& constMap = GetViewLevelGNodeGStyleMap__();
    const auto& iter = constMap.find(viewId);
    if (iter != constMap.end())
    {
        return iter->second->GetGNodeCategoryToGNodeGStyleMap__();
    }
    return s_emptyUniIdentityElementIdMap;
}

DBOBJECT_DATA_DEFINE(CustomizerGStyleManager)
{
    m_OwnerElement = nullptr;
}

bool CustomizerGStyleManager::SetOwnerElement(gcmp::IElement * pOwnerElement)
{
    m_OwnerElement = pOwnerElement;
    return true;
}

gcmp::IDocument * CustomizerGStyleManager::GetDocument() const
{
    if (!m_OwnerElement)
    {
        return nullptr;
    }
    return m_OwnerElement->GetDocument();
}

gcmp::ElementId CustomizerGStyleManager::GetOwnerElementId() const
{
    if (!m_OwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_OwnerElement->GetElementId();
}

void CustomizerGStyleManager::UpdateForWeakParentDeletion(const std::set<gcmp::ElementId>& deletedElementIds)
{
    const IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMP",L"2024-03-30");

    auto& elementToElementGStyleDataMap = GetElementToElementGStyleDataMapFW__();
    // 遍历所有图元的重载信息。下面遍历的方式在图元很多时性能不好，实际项目需要优化。
    for (auto elementToElementGStyleDataPair = elementToElementGStyleDataMap.begin(); elementToElementGStyleDataPair != elementToElementGStyleDataMap.end();)
    {
        ElementId elemId = elementToElementGStyleDataPair->first;
        // 如果图元被删除，则删除对应的数据
        if (deletedElementIds.find(elemId) != deletedElementIds.end())
        {
            elementToElementGStyleDataPair = elementToElementGStyleDataMap.erase(elementToElementGStyleDataPair);
            continue;
        }
        OwnerPtr<ElementGStyleData>& opElementGStyleData = elementToElementGStyleDataPair->second;
        DBG_WARN_AND_CONTINUE_UNLESS(opElementGStyleData, L"opElementGStyleData为空",L"GDMP",L"2024-03-30");
        auto& viewLevelGNodeGStyleMap = opElementGStyleData->GetViewLevelGNodeGStyleMapFW();
        for (auto viewLevelGNodeGStylePair = viewLevelGNodeGStyleMap.begin(); elementToElementGStyleDataPair != viewLevelGNodeGStyleMap.end();)
        {
            // 如果是图被删除，则删除对应的数据
            ElementId viewId = viewLevelGNodeGStylePair->first;
            if (deletedElementIds.find(viewId) != deletedElementIds.end())
            {
                viewLevelGNodeGStylePair = viewLevelGNodeGStyleMap.erase(viewLevelGNodeGStylePair);
            }
        }
    }
}

void CustomizerGStyleManager::ReportParents(gcmp::IElementParentReporter & reporter) const
{
    const IElement* pOwnerElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pOwnerElement, L"pOwnerElement为空",L"GDMP",L"2024-03-30");
    reporter.ReportStrong(pOwnerElement->GetElementId());

    const auto& elementToElementGStyleDataMap = GetElementToElementGStyleDataMap__();
    for (const auto& elementToElementGStyleDataPair : elementToElementGStyleDataMap)
    {
        // CustomizerGStyleManager管理的所有有样式重载的图元
        ElementId elemId = elementToElementGStyleDataPair.first;
        reporter.ReportWeak(elemId);
        const OwnerPtr<ElementGStyleData>& opElementGStyleData = elementToElementGStyleDataPair.second;

        ElementId docElemGStyleId;
        if (opElementGStyleData->GetElementGStyle(docElemGStyleId))
        {
            // 文档级图元样式重载的样式
            reporter.ReportWeak(docElemGStyleId);
        }

        for (auto& iter : opElementGStyleData->GetGNodeNameGStyles())
        {
            // 文档级图形节点按照节点样式名称重载的样式
            reporter.ReportWeak(iter.second);
        }
        for (auto& iter : opElementGStyleData->GetGNodeCategoryGStyles())
        {
            // 文档级图形节点按照节点样式类别重载的样式
            reporter.ReportWeak(iter.second);
        }

        for (const auto& viewLevelGNodeGStylePair : opElementGStyleData->GetViewLevelGNodeGStyleMap())
        {
            // 重载的视图
            reporter.ReportWeak(viewLevelGNodeGStylePair.first);
            const OwnerPtr<ElementGStyleData>& opViewElementGStyleData = viewLevelGNodeGStylePair.second;
            DBG_WARN_AND_CONTINUE_UNLESS(opElementGStyleData, L"opElementGStyleData为空",L"GDMP",L"2024-03-30");

            ElementId viewElemGStyleId;
            if (opViewElementGStyleData->GetElementGStyle(viewElemGStyleId))
            {
                // 视图级图元样式重载的样式
                reporter.ReportWeak(viewElemGStyleId);
            }

            for (auto& iter : opViewElementGStyleData->GetGNodeNameGStyles())
            {
                // 视图级图形节点按照节点样式名称重载的样式
                reporter.ReportWeak(iter.second);
            }
            for (auto& iter : opViewElementGStyleData->GetGNodeCategoryGStyles())
            {
                // 视图级图形节点按照节点样式类别重载的样式
                reporter.ReportWeak(iter.second);
            }
        }
    }
}

gcmp::NdbObject* Sample::CustomizerGStyleManager::GetTopOwnerObject() const
{
    return nullptr;
}

CustomizerGStyleManager * Sample::CustomizerGStyleManager::CreateOrGet(gcmp::IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMP",L"2024-03-30");
    CustomizerGStyleManager* pStyleLib = CustomizerGStyleManager::Get(pDoc);
    // 有则返回
    if (pStyleLib)
    {
        return pStyleLib;
    }
    // 无则创建
    OwnerPtr<CustomizerGStyleManager> opGraphicsStyleLib = NEW_AS_OWNER_PTR(CustomizerGStyleManager);
    pStyleLib = opGraphicsStyleLib.get();
    IGenericElement* pElement = IGenericElement::Create(
        pDoc,
        TransferOwnership(opGraphicsStyleLib),
        CustomizerGStyleManager::GetClassId().GetGuid(),
        ElementCreationOptions::Normal
    );

    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElement, L"pElement为空",L"GDMP",L"2024-03-30");
    IElementStatus *pStatus = pElement->GetStatus();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pStatus, L"pStatus为空",L"GDMP",L"2024-03-30");
    // 不可见，文档级单例
    pStatus->SetIsVisible(false);
    gcmp::ElementUtils::MakeElementUnique(pElement, CustomizerGStyleManager::GetClassId().GetGuid());
    return pStyleLib;
}

CustomizerGStyleManager * Sample::CustomizerGStyleManager::Get(gcmp::IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMP",L"2024-03-30");
    IElement* pUniqueElem = pDoc->GetUniqueElementByClassUid(UniIdentity(CustomizerGStyleManager::GetClassId().GetGuid()));
    if (!pUniqueElem)
    {
        return nullptr;
    }

    IGenericElement * ppStyleLibElement = quick_cast<IGenericElement>(pUniqueElem);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(ppStyleLibElement, L"ppStyleLibElement为空",L"GDMP",L"2024-03-30");
    CustomizerGStyleManager* pStyleLib = quick_cast<CustomizerGStyleManager>(ppStyleLibElement->GetExternalObject());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStyleLib, L"pStyleLib为空",L"GDMP",L"2024-03-30");

    return pStyleLib;
}

void Sample::CustomizerGStyleManager::InitializeGStyleCategory()
{
    IElement* pOwnerElem = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pOwnerElem, L"pOwnerElem为空",L"GDMP",L"2024-03-30");
    IDocument* pDoc = pOwnerElem->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMP",L"2024-03-30");

    // 代码方式创建类别和类别样式
    ICategoryLibrary* pCategoryLib = ICategoryLibrary::Get(pDoc);
    OwnerPtr<ICategory> opCategoryA = ICategory::Create(s_category_id_CategoryA, L"类别A", L"用于显示样式重载测试");
    OwnerPtr<ICategory> opCategoryB = ICategory::Create(s_category_id_CategoryB, L"类别B", L"用于显示样式重载测试");
    OwnerPtr<ICategory> opCategoryC = ICategory::Create(s_category_id_CategoryC, L"类别C", L"用于显示样式重载测试");
    OwnerPtr<ICategory> opCategoryD = ICategory::Create(s_category_id_CategoryD, L"类别D", L"用于显示样式重载测试");
    pCategoryLib->AddCategory(TransferOwnership(opCategoryA));
    pCategoryLib->AddCategory(TransferOwnership(opCategoryB));
    pCategoryLib->AddCategory(TransferOwnership(opCategoryC));
    pCategoryLib->AddCategory(TransferOwnership(opCategoryD));

    // 用于可见图元的类别必须创建类别样式
    OwnerPtr<IGraphicsStyleData> opDefaultGStyleData = IGraphicsStyleData::Create();
    opDefaultGStyleData->Reset();
   
    IGraphicsStyleManager* pGStyleManager = pDoc->GetGraphicsStyleManager();
    pGStyleManager->CreateGraphicsStyleForCategory(s_category_id_CategoryA, *opDefaultGStyleData);
    pGStyleManager->CreateGraphicsStyleForCategory(s_category_id_CategoryB, *opDefaultGStyleData);
    opDefaultGStyleData->SetColor(Color::Red);
    pGStyleManager->CreateGraphicsStyleForCategory(s_category_id_CategoryC, *opDefaultGStyleData);
    opDefaultGStyleData->SetColor(Color::Blue);
    pGStyleManager->CreateGraphicsStyleForCategory(s_category_id_CategoryD, *opDefaultGStyleData);

    // 加载XML文件，创建对应的类别和类别样式
    std::wstring configFilePathFull = FilePath::Combine(FileSystem::GetExeDirPath(), L"SampleData\\GraphicsStyle.xml");
    m_opGStyleConfig = GraphicsStyleConfig::Load(configFilePathFull);
    if (m_opGStyleConfig)
    {
        for (auto& iter : m_opGStyleConfig->GetCategoryStyles())
        {
            OwnerPtr<ICategory> opCategory = ICategory::Create(iter->CategoryUid, iter->Name, iter->Name);
            pCategoryLib->AddCategory(TransferOwnership(opCategory));
            pGStyleManager->CreateGraphicsStyleForCategory(iter->CategoryUid, *iter->m_opStyleData);
        }
    }
}

std::map<std::wstring, const gcmp::ICategory*> Sample::CustomizerGStyleManager::GetGStyleCategories() const
{
    // 代码方式创建的类别和类别样式
    std::map<std::wstring, const gcmp::ICategory*> result;
    ICategoryLibrary* pCategoryLib = ICategoryLibrary::Get(GetOwnerElement()->GetDocument());
    if (const ICategory* pCategory = pCategoryLib->GetCategory(s_category_id_CategoryA)) {
        result[pCategory->GetDisplayName()] = pCategory;
    }
    if (const ICategory* pCategory = pCategoryLib->GetCategory(s_category_id_CategoryB)) {
        result[pCategory->GetDisplayName()] = pCategory;
    }
    if (const ICategory* pCategory = pCategoryLib->GetCategory(s_category_id_CategoryC)) {
        result[pCategory->GetDisplayName()] = pCategory;
    }
    if (const ICategory* pCategory = pCategoryLib->GetCategory(s_category_id_CategoryD)) {
        result[pCategory->GetDisplayName()] = pCategory;
    }

    DBG_WARN_AND_RETURN_UNLESS(m_opGStyleConfig, result, L"m_opGStyleConfig为空",L"GDMP",L"2024-03-30");
    // XML方式创建的类别和类别样式
    for (auto& iter : m_opGStyleConfig->GetCategoryStyles())
    {
        const ICategory* pCategory = pCategoryLib->GetCategory(iter->CategoryUid);
        result[iter->Name] = pCategory;
    }
    return result;
}

void Sample::CustomizerGStyleManager::GetElementGStyle(gcmp::ElementId elemId, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* elemGStyleData = nullptr;
    if (GetElemMap(elemId, elemGStyleData))
    {
        elemGStyleData->GetElementGStyle(gStyleId);
    }
}

void Sample::CustomizerGStyleManager::GetViewElementGStyle(gcmp::ElementId elemId, gcmp::ElementId viewId, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* elemGStyleData = nullptr;
    if (GetElemMap(elemId, elemGStyleData))
    {
        elemGStyleData->GetViewElementGStyle(viewId, gStyleId);
    }
}

void Sample::CustomizerGStyleManager::GetGNodeNameGStyle(gcmp::ElementId elemId, std::wstring gNodeName, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* elemGStyleData = nullptr;
    if (GetElemMap(elemId, elemGStyleData))
    {
        elemGStyleData->GetGNodeNameGStyle(gNodeName, gStyleId);
    }
}

void Sample::CustomizerGStyleManager::GetGNodeCategoryGStyle(gcmp::ElementId elemId, gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* elemGStyleData = nullptr;
    if (GetElemMap(elemId, elemGStyleData))
    {
        elemGStyleData->GetGNodeCategoryGStyle(gNodeCategory, gStyleId);
    }
}

void Sample::CustomizerGStyleManager::GetViewGNodeNameGStyle(gcmp::ElementId elemId, gcmp::ElementId viewId, std::wstring gNodeName, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* elemGStyleData = nullptr;
    if (GetElemMap(elemId, elemGStyleData))
    {
        elemGStyleData->GetViewGNodeNameGStyle(viewId, gNodeName, gStyleId);
    }
}

void Sample::CustomizerGStyleManager::GetViewGNodeCategoryGStyle(gcmp::ElementId elemId, gcmp::ElementId viewId, gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId) const
{
    const ElementGStyleData* elemGStyleData = nullptr;
    if (GetElemMap(elemId, elemGStyleData))
    {
        elemGStyleData->GetViewGNodeCategoryGStyle(viewId, gNodeCategory, gStyleId);
    }
}

void Sample::CustomizerGStyleManager::UpdateElementGStyle(gcmp::ElementId elemId, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* elemGStyleData = GetOrAddElemMap(elemId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(elemGStyleData, L"elemGStyleData为空",L"GDMP",L"2024-03-30");
    elemGStyleData->UpdateElementGStyle(gStyleId);
}

void Sample::CustomizerGStyleManager::UpdateViewElementGStyle(gcmp::ElementId elemId, gcmp::ElementId viewId, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* elemGStyleData = GetOrAddElemMap(elemId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(elemGStyleData, L"elemGStyleData为空",L"GDMP",L"2024-03-30");
    elemGStyleData->UpdateViewElementGStyle(viewId, gStyleId);
}

void Sample::CustomizerGStyleManager::UpdateGNodeNameGStyle(gcmp::ElementId elemId, std::wstring gNodeName, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* elemGStyleData = GetOrAddElemMap(elemId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(elemGStyleData, L"elemGStyleData为空",L"GDMP",L"2024-03-30");
    elemGStyleData->UpdateGNodeNameGStyle(gNodeName, gStyleId);
}

void Sample::CustomizerGStyleManager::UpdateGNodeCategoryGStyle(gcmp::ElementId elemId, gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* elemGStyleData = GetOrAddElemMap(elemId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(elemGStyleData, L"elemGStyleData为空",L"GDMP",L"2024-03-30");
    elemGStyleData->UpdateGNodeCategoryGStyle(gNodeCategory, gStyleId);
}

void Sample::CustomizerGStyleManager::UpdateViewGNodeNameGStyle(gcmp::ElementId elemId, gcmp::ElementId viewId, std::wstring gNodeName, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* elemGStyleData = GetOrAddElemMap(elemId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(elemGStyleData, L"elemGStyleData为空",L"GDMP",L"2024-03-30");
    elemGStyleData->UpdateViewGNodeNameGStyle(viewId, gNodeName, gStyleId);
}

void Sample::CustomizerGStyleManager::UpdateViewGNodeCategoryGStyle(gcmp::ElementId elemId, gcmp::ElementId viewId, gcmp::UniIdentity gNodeCategory, gcmp::ElementId & gStyleId)
{
    ElementGStyleData* elemGStyleData = GetOrAddElemMap(elemId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(elemGStyleData, L"elemGStyleData为空",L"GDMP",L"2024-03-30");
    elemGStyleData->UpdateViewGNodeCategoryGStyle(viewId, gNodeCategory, gStyleId);
}

const std::unordered_map<std::wstring, gcmp::ElementId, std::hash<std::wstring>>& Sample::CustomizerGStyleManager::GetGNodeNameGStyles(gcmp::ElementId elemId) const
{
    const ElementGStyleData* pElemGStyleData = nullptr;
    GetElemMap(elemId, pElemGStyleData);
    if (pElemGStyleData)
    {
        return pElemGStyleData->GetGNodeNameGStyles();
    }
    return s_emptyStringElementIdMap;
}

const std::unordered_map<gcmp::UniIdentity, gcmp::ElementId, gcmp::UniIdentityHash>& Sample::CustomizerGStyleManager::GetGNodeCategoryGStyles(gcmp::ElementId elemId) const
{
    const ElementGStyleData* pElemGStyleData = nullptr;
    GetElemMap(elemId, pElemGStyleData);
    if (pElemGStyleData)
    {
        return pElemGStyleData->GetGNodeCategoryGStyles();
    }
    return s_emptyUniIdentityElementIdMap;
}

const std::unordered_map<std::wstring, gcmp::ElementId, std::hash<std::wstring>>& Sample::CustomizerGStyleManager::GetViewGNodeNameGStyles(gcmp::ElementId elemId, gcmp::ElementId viewId) const
{
    const ElementGStyleData* pElemGStyleData = nullptr;
    GetElemMap(elemId, pElemGStyleData);
    if (pElemGStyleData)
    {
        return pElemGStyleData->GetViewGNodeNameGStyles(viewId);
    }
    return s_emptyStringElementIdMap;
}

const std::unordered_map<gcmp::UniIdentity, gcmp::ElementId, gcmp::UniIdentityHash>& Sample::CustomizerGStyleManager::GetViewGNodeCategoryGStyles(gcmp::ElementId elemId, gcmp::ElementId viewId) const
{
    const ElementGStyleData* pElemGStyleData = nullptr;
    GetElemMap(elemId, pElemGStyleData);
    if (pElemGStyleData)
    {
        return pElemGStyleData->GetViewGNodeCategoryGStyles(viewId);
    }
    return s_emptyUniIdentityElementIdMap;
}

ElementGStyleData* Sample::CustomizerGStyleManager::GetOrAddElemMap(gcmp::ElementId elemId)
{
    auto& mutableMap = GetElementToElementGStyleDataMapFW__();
    const auto& iter = mutableMap.find(elemId);
    if (iter == mutableMap.end())
    {
        OwnerPtr<ElementGStyleData> opElementGStyleData = ElementGStyleData::Create();
        mutableMap[elemId] = TransferOwnership(opElementGStyleData);
        return mutableMap.find(elemId)->second.get();
    }
    else
    {
        auto& mutableMap = GetElementToElementGStyleDataMapFW__();
        return mutableMap.find(elemId)->second.get();
    }
}

bool Sample::CustomizerGStyleManager::GetElemMap(gcmp::ElementId elemId, const ElementGStyleData*& pElemGStyleData) const
{
    const auto& constMap = GetElementToElementGStyleDataMap__();
    const auto& iter = constMap.find(elemId);
    if (iter == constMap.end())
    {
        return false;
    }
    else
    {
        pElemGStyleData = constMap.find(elemId)->second.get();
        return true;
    }
}

